﻿using Externals.Compression;
using Externals.Compression.Zip;
using Externals.Compression.Checksums;
using System;
using System.Collections.Generic;
using System.Text;

namespace Apewer.Internals
{

    internal class ZipUtility
    {

        /// <summary>压缩字典为 .ZIP 文件。</summary>
        /// <param name="files">由文件名和文件内容组成的字典。</param>
        public static System.IO.MemoryStream ToZip(Dictionary<string, byte[]> files)
        {
            var memorystream = new System.IO.MemoryStream();
            if (files == null) return memorystream;

            var zipstream = new ZipOutputStream(memorystream);
            zipstream.SetLevel(1);

            foreach (var file in files)
            {
                var crc = new Crc32();
                crc.Reset();
                crc.Update(file.Value);

                var zipentry = new ZipEntry(file.Key);
                zipentry.CompressionMethod = CompressionMethod.Deflated;
                //vzipentry.Size = vfile.Value.LongLength;
                zipentry.Crc = crc.Value;
                zipentry.IsUnicodeText = true;

                zipstream.PutNextEntry(zipentry);
                zipstream.Write(file.Value, 0, file.Value.Length);
                zipstream.CloseEntry();
            }

            zipstream.IsStreamOwner = false;
            zipstream.Finish();
            zipstream.Flush();
            zipstream.Close();

            return memorystream;
        }

        /// <summary>解压 .ZIP 文件为字典。</summary>
        public static Dictionary<string, byte[]> FromZip(byte[] zipdata)
        {
            var result = new Dictionary<string, byte[]>();
            if (zipdata == null) return result;
            if (zipdata.LongLength < 1) return result;

            var packagememory = new System.IO.MemoryStream(zipdata);
            try
            {
                var zipstream = new ZipInputStream(packagememory);
                while (true)
                {
                    var entry = zipstream.GetNextEntry();
                    if (entry == null) break;

                    if (entry.IsFile)
                    {
                        var cellname = entry.Name;
                        var celldata = new byte[0];
                        {
                            var cellstream = new System.IO.MemoryStream();
                            while (true)
                            {
                                var blockdata = new byte[1024];
                                var blockread = zipstream.Read(blockdata, 0, 1024);
                                if (blockread < 1) break;
                                cellstream.Write(blockdata, 0, blockread);
                            }
                            celldata = cellstream.ToArray();
                            cellstream.Dispose();
                        }
                        if (result.ContainsKey(cellname)) result[cellname] = celldata;
                        else result.Add(cellname, celldata);
                    }
                }
                zipstream.Dispose();
            }
            catch { }
            packagememory.Dispose();
            return result;
        }

    }

}
